package com.bridgeintelligent.tag.webserver.dim.mgmt.service.report;

import com.bridgeintelligent.tag.mapper.ReportMapper;
import com.bridgeintelligent.tag.webserver.dim.mgmt.api.report.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class ReportServiceImpl implements ReportService {

    private ReportMapper reportMapper;

    @Override
    public List<ReportSystemUseInfo> systemUseInfo(String sortWord) {

        List<ReportSystemUseInfo> infos = reportMapper.systemUseInfo(sortWord);
        ReportSystemUseInfo totalInfo = reportMapper.systemUseInfoTotal();
        ReportSystemUseInfo timeInfo = reportMapper.systemUseInfoByTime(lastMonth());
        ReportMonitorBordInfo bordInfo = reportMapper.monitorBordInfo();
        //处理汇总数据
        if (totalInfo == null) {
            totalInfo = new ReportSystemUseInfo();
        }
        totalInfo.setDatetime("汇总");
        if (timeInfo != null){
            totalInfo.setUserNum(timeInfo.getUserNum());
            totalInfo.setBaseTotal(timeInfo.getBaseTotal());
            totalInfo.setDingzhiAllTotal(timeInfo.getDingzhiAllTotal());
            totalInfo.setDingzhiTotal(timeInfo.getDingzhiTotal());
            totalInfo.setDingzhiExpireNum(timeInfo.getDingzhiExpireNum());
            totalInfo.setCombinationAllTotal(timeInfo.getCombinationAllTotal());
            totalInfo.setCombinationTotal(timeInfo.getCombinationTotal());
            totalInfo.setCombinationExpireNum(timeInfo.getCombinationExpireNum());
            totalInfo.setDimTotal(timeInfo.getDimTotal());
            totalInfo.setCustomerAllTotal(timeInfo.getCustomerAllTotal());
            totalInfo.setCustomerExpireNum(timeInfo.getCustomerExpireNum());
            totalInfo.setCustomerTotal(timeInfo.getCustomerTotal());
        }
        if (bordInfo != null){
            totalInfo.setActiveNum(bordInfo.getActiveNum());
            totalInfo.setBaseDimNum(bordInfo.getBaseUseNum());
            totalInfo.setDimNum(bordInfo.getUseNum());
        }

        totalInfo.setActivePrecent(compute(totalInfo.getActiveNum(),totalInfo.getUserNum()));
        totalInfo.setBaseDimPrecent(compute(totalInfo.getBaseDimNum(),totalInfo.getBaseTotal()));
        totalInfo.setDimPrecent(compute(totalInfo.getDimNum(),totalInfo.getDimTotal()));

        if (CollectionUtils.isEmpty(infos)){
            infos = new ArrayList<>();
        }
        infos.add(totalInfo);
        return infos;
    }

    @Override
    public List<ReportOrgUseInfo> orgUseInfo(String startTime,String endTime,String sortWord) {

        List<ReportOrgUseInfo> infos = reportMapper.orgUseInfo(startTime,endTime,sortWord);
        infos = Optional.ofNullable(infos).orElse(new ArrayList<>());

        //处理每月明细
        List<ReportOrgMonthInfo> reportOrgMonthInfos = reportMapper.orgMonthInfo(startTime,endTime);
        Map<String, List<ReportOrgMonthInfo>> orgMap = reportOrgMonthInfos.stream().collect(Collectors.groupingBy(ReportOrgMonthInfo::getOrgId));
        infos.forEach(e->{
            List<ReportOrgMonthInfo> orgMonths = orgMap.get(e.getOrgId());
            if (!CollectionUtils.isEmpty(orgMonths)){
                e.setMonths(orgMonths.stream().sorted(Comparator.comparing(ReportOrgMonthInfo::getDateTime)).collect(Collectors.toList()));
            }
            orgMonths = null;
        });
        return infos;
    }

    @Override
    public ReportPage<ReportOrgUseInfo> orgUseInfoPage(String sortWord, String orgId, String startTime,String endTime,Integer pageNum, Integer pageSize) {
        ReportPage<ReportOrgUseInfo> pageInfo;
        List<ReportOrgUseInfo> infos;
        if(StringUtils.isEmpty(orgId)){
            Page page = PageHelper.startPage(pageNum, pageSize);
            infos = reportMapper.orgUseInfo(startTime,endTime,sortWord);
            pageInfo = new ReportPage<>();
            pageInfo.setContent(infos);
            pageInfo.setTotalPages(page.getPages());
            pageInfo.setTotalElements(page.getTotal());
            pageInfo.setSize(page.getPageSize());
            pageInfo.setRequestPager(pageNum);
        }else{
            //此处为什么不直接传入orgId查询，因为页面要显示出实际的排名
            infos = reportMapper.orgUseInfo(startTime,endTime,sortWord);
            List<ReportOrgUseInfo> filters = infos.stream().filter(e -> e.getOrgId().equals(orgId)).collect(Collectors.toList());
            pageInfo = new ReportPage<>();
            pageInfo.setContent(filters);
            pageInfo.setTotalPages(1);
            pageInfo.setTotalElements(1l);
            pageInfo.setSize(pageSize);
            pageInfo.setRequestPager(pageNum);
        }
        return pageInfo;
    }

    @Override
    public List<ReportOrgUseInfo> orgUseInfoWithTotal(String sortWord, String orgId, String startTime, String endTime) {
        List<ReportOrgUseInfo> infos = reportMapper.orgUseInfo(startTime,endTime,sortWord);
        infos = Optional.ofNullable(infos).orElse(new ArrayList<>());
        if (!StringUtils.isEmpty(orgId)){
            infos = infos.stream().filter(e -> e.getOrgId().equals(orgId)).collect(Collectors.toList());
        }

        //计算汇总数据
        //先处理能直接sum的数据
        ReportOrgUseInfo sumInfo = reportMapper.orgUseInfoSum(startTime, endTime);
        sumInfo = Optional.ofNullable(sumInfo).orElse(new ReportOrgUseInfo());
        sumInfo.setOrderNum("汇总");
        sumInfo.setOrgName("-");

        //再处理截至到结束时间节点进行sum的数据
        ReportOrgUseInfo endSumInfo = reportMapper.orgUseLastTimeSum(endTime);
        endSumInfo = Optional.ofNullable(endSumInfo).orElse(new ReportOrgUseInfo());

        sumInfo.setUserNum(endSumInfo.getUserNum());
        sumInfo.setActiveNum(endSumInfo.getActiveNum());
        sumInfo.setActivePrecent(compute(sumInfo.getActiveNum(),sumInfo.getUserNum()));
        sumInfo.setDingzhiAllTotal(endSumInfo.getDingzhiAllTotal());
        sumInfo.setDingzhiTotal(endSumInfo.getDingzhiTotal());
        sumInfo.setDingzhiExpireNum(endSumInfo.getDingzhiExpireNum());
        sumInfo.setCombinationAllTotal(endSumInfo.getCombinationAllTotal());
        sumInfo.setCombinationTotal(endSumInfo.getCombinationTotal());
        sumInfo.setCombinationExpireNum(endSumInfo.getCombinationExpireNum());
        sumInfo.setCustomerAllTotal(endSumInfo.getCustomerAllTotal());
        sumInfo.setCustomerTotal(endSumInfo.getCustomerTotal());
        sumInfo.setCustomerExpireNum(endSumInfo.getCustomerExpireNum());

        //计算基础标签总量和标签总量
        Integer baseTotal = reportMapper.findBaseTotal(endTime);
        Integer dimTotal = reportMapper.findDimTotal(endTime);
        sumInfo.setBaseTotal(baseTotal == null ? 0 : baseTotal);
        sumInfo.setDimTotal(dimTotal == null ? 0 : dimTotal);
        //计算使用基础标签个数和标签个数
        ReportOrgUseInfo actualSumInfo = reportMapper.orgUseActualTimeSum(startTime, endTime);
        actualSumInfo = Optional.ofNullable(actualSumInfo).orElse(new ReportOrgUseInfo());
        sumInfo.setBaseDimNum(actualSumInfo.getBaseDimNum());
        sumInfo.setBaseDimPrecent(compute(sumInfo.getBaseDimNum(),sumInfo.getBaseTotal()));
        sumInfo.setDimNum(actualSumInfo.getDimNum());
        sumInfo.setDimPrecent(compute(sumInfo.getDimNum(),sumInfo.getDimTotal()));
        infos.add(sumInfo);
        return infos;
    }

    @Override
    public List<ReportHotDimInfo> hotDimInfo(String dimType,String secDimType) {
        //节前只做了对所有标签综合得分进行排序
        List<ReportHotDimInfo> allDatas = reportMapper.hotDimInfo(dimType);
        if ( ( allDatas == null ) || ( allDatas.isEmpty() ) ) {
            return new ArrayList<>();
        }
        List<ReportHotDimInfo> targetDatas = new ArrayList<>();
        DataSorter.setScoreST(allDatas);
        if(StringUtils.isNotEmpty(dimType)&&(!dimType.equals(TYPE_FIVE))){
            targetDatas = allDatas.stream().filter(e->dimType.equals(e.getDimType())).collect(Collectors.toList());
            Collections.sort(targetDatas, Comparator.comparing(ReportHotDimInfo::getScoreST).reversed());
            return targetDatas;
        }else if(StringUtils.isNotEmpty(dimType)&&StringUtils.isNotEmpty(secDimType)){
            targetDatas = allDatas.stream().filter(e->secDimType.equals(e.getDimType())).collect(Collectors.toList());
            Collections.sort(targetDatas, Comparator.comparing(ReportHotDimInfo::getScoreST).reversed());
            return targetDatas;
        }else{
            Collections.sort(allDatas, Comparator.comparing(ReportHotDimInfo::getScoreST).reversed());
            return allDatas;
        }
    }

    @Override
    public ReportPage<ReportCombinationCustomizeInfo> combinationBustomizeInfo(String selectType,String sortWord, Integer pageNum, Integer pageSize) {
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<ReportCombinationCustomizeInfo> infos = reportMapper.combinationBustomizeInfo(selectType,sortWord);
        ReportPage<ReportCombinationCustomizeInfo> pageInfo = new ReportPage<>();
        pageInfo.setContent(infos);
        pageInfo.setTotalPages(page.getPages());
        pageInfo.setTotalElements(page.getTotal());
        pageInfo.setSize(page.getPageSize());
        pageInfo.setRequestPager(pageNum);
        return pageInfo;
    }

    @Override
    public ReportPage<ReportCustomerUseInfo> customerUseInfo(String sortWord, Integer pageNum, Integer pageSize) {
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<ReportCustomerUseInfo> infos = reportMapper.customerUseInfo(sortWord);
        ReportPage<ReportCustomerUseInfo> pageInfo = new ReportPage<>();
        pageInfo.setContent(infos);
        pageInfo.setTotalPages(page.getPages());
        pageInfo.setTotalElements(page.getTotal());
        pageInfo.setSize(page.getPageSize());
        pageInfo.setRequestPager(pageNum);
        return pageInfo;
    }

    @Override
    public ReportPage<ReportCustomerCreateInfo> customerCreateInfo(String sortWord, Integer pageNum, Integer pageSize) {
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<ReportCustomerCreateInfo> infos = reportMapper.customerCreateInfo(sortWord);
        ReportPage<ReportCustomerCreateInfo> pageInfo = new ReportPage<>();
        pageInfo.setContent(infos);
        pageInfo.setTotalPages(page.getPages());
        pageInfo.setTotalElements(page.getTotal());
        pageInfo.setSize(page.getPageSize());
        pageInfo.setRequestPager(pageNum);
        return pageInfo;
    }

    @Override
    public List<ReportSystemModelUseInfo> systemModelUseInfo() {
        return reportMapper.systemModelUseInfo();
    }

    @Override
    public ReportMonitorBordInfo monitorBordInfo() {
        ReportMonitorBordInfo info = reportMapper.monitorBordInfo();
        if (info == null){
            info = new ReportMonitorBordInfo();
        }
        return info;
    }

    @Override
    public List<OrgInfo> findOrgList(String orgName) {
        return reportMapper.findOrgList(orgName);
    }

    @Override
    public List<ReportSystemModelDetailInfo> modelDetailInfo(String modelType, String sortWord) {
        List<ReportSystemModelDetailInfo> infos = reportMapper.modelDetailInfo(modelType,sortWord);
        if (infos == null){
            infos = new ArrayList<>();
        }
        return infos;
    }


    @Override
    public List<ReportSystemModelTypeInfo> modelTypeInfo() {
        return reportMapper.modelTypeInfo();
    }

    @Override
    public Map<Integer, ReportSystemModelDetailInfo> modelDetailMaxInfo() {
        List<ReportSystemModelDetailInfo> infos = reportMapper.modelDetailMaxInfo();
        if (infos == null){
            infos = new ArrayList<>();
        }
        return infos.stream().collect(Collectors.toMap(ReportSystemModelDetailInfo::getModelType, e -> e));

    }

    @Override
    public ReportPage<OrgUserLoginModel> orgUserLogin(String orgId, String sortWord,String startTime,String endTime,Integer pageNum,Integer pageSize) {
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<OrgUserLoginModel> infos = reportMapper.orgUserLogin(orgId,sortWord,startTime,endTime);
        ReportPage<OrgUserLoginModel> pageInfo = new ReportPage<>();
        pageInfo.setContent(infos);
        pageInfo.setTotalPages(page.getPages());
        pageInfo.setTotalElements(page.getTotal());
        pageInfo.setSize(page.getPageSize());
        pageInfo.setRequestPager(pageNum);
        return pageInfo;
    }

    @Override
    public ReportPage<OrgUserCustomerModel> orgUserCustomer(String orgId, String sortWord, @Param("startTime") String startTime, @Param("endTime") String endTime,Integer pageNum, Integer pageSize) {
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<OrgUserCustomerModel> infos = reportMapper.orgUserCustomer(orgId,sortWord,startTime,endTime);
        ReportPage<OrgUserCustomerModel> pageInfo = new ReportPage<>();
        pageInfo.setContent(infos);
        pageInfo.setTotalPages(page.getPages());
        pageInfo.setTotalElements(page.getTotal());
        pageInfo.setSize(page.getPageSize());
        pageInfo.setRequestPager(pageNum);
        return pageInfo;
    }

    @Override
    public ReportPage<OrgUserDimModel> orgUserDim(String orgId, String sortWord,@Param("startTime") String startTime,@Param("endTime") String endTime, Integer pageNum, Integer pageSize) {
        Page page = PageHelper.startPage(pageNum, pageSize);
        List<OrgUserDimModel> infos = reportMapper.orgUserDim(orgId,sortWord,startTime,endTime);
        ReportPage<OrgUserDimModel> pageInfo = new ReportPage<>();
        pageInfo.setContent(infos);
        pageInfo.setTotalPages(page.getPages());
        pageInfo.setTotalElements(page.getTotal());
        pageInfo.setSize(page.getPageSize());
        pageInfo.setRequestPager(pageNum);
        return pageInfo;
    }

    private String lastMonth(){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        LocalDate date = LocalDate.now();
        date = date.minusMonths(1);
        return date.format(formatter);
    }

    public BigDecimal compute(Integer k1,Integer k2){
        BigDecimal n1 = BigDecimal.valueOf(k1);
        BigDecimal n2 = BigDecimal.valueOf(k2);
        if (k2 == 0 || k1 == 0){
            return new BigDecimal("0.00");
        }
        return n1.multiply(new BigDecimal("100")).divide(n2,2,BigDecimal.ROUND_HALF_UP);
    }
}
